"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Commander = exports.EventsTypes = void 0;
const events_1 = require("events");
const helpers_1 = require("./helpers");
var EventsTypes;
(function (EventsTypes) {
    EventsTypes["COMMAND_NOT_FOUNDED"] = "command_not_founded";
    EventsTypes["COMMAND_EXECUTION_ERROR"] = "command_execution_error";
})(EventsTypes = exports.EventsTypes || (exports.EventsTypes = {}));
/**
 * Class for commands managment
 */
class Commander {
    constructor() {
        this.commands = [];
        this.listener = new events_1.EventEmitter();
        this.addCommand = (command) => {
            this.commands.push(command);
        };
        /**
         * Middleware that founds and calls commands handlers
         */
        this.middleware = (context, next) => __awaiter(this, void 0, void 0, function* () {
            if (!context.text)
                return next();
            const command = this.findCommand(context.text);
            if (!command) {
                return this.listener.emit(EventsTypes.COMMAND_NOT_FOUNDED, context);
            }
            const args = this.matchAndParseCommandArgs(context.text, command.options.triggers.regex);
            try {
                yield command.options.handler(context, args);
            }
            catch (_a) {
                this.listener.emit(EventsTypes.COMMAND_EXECUTION_ERROR, context, command);
            }
        });
    }
    /**
     * Method than founds command by message text
     */
    findCommand(text) {
        return this.commands.find(({ options }) => (text && options.triggers.regex.test(text)));
    }
    matchAndParseCommandArgs(text, regexTrigger) {
        const matches = text.match(regexTrigger);
        const args = matches && (matches === null || matches === void 0 ? void 0 : matches.groups)
            ? (0, helpers_1.parseNamedRegexGroups)(matches.groups)
            : {};
        return args;
    }
}
exports.Commander = Commander;
